package cn.westv.scps.web.controller.sms.massage;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.annotation.Resource;

import org.apache.commons.codec.binary.Base64;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.yunpian.sdk.model.Result;
import com.yunpian.sdk.model.SmsSingleSend;

import cn.westv.scps.constant.ConfigCodeConstant;
import cn.westv.scps.constant.DBconstant;
import cn.westv.scps.constant.SmsTplCodeConstant;
import cn.westv.scps.domain.AreaSeverEntity;
import cn.westv.scps.domain.BikeOwnerEntity;
import cn.westv.scps.domain.SmsMessageRecordEntity;
import cn.westv.scps.exception.NoHaveValidateCode;
import cn.westv.scps.exception.SendSmsOutOfRangeException;
import cn.westv.scps.exception.SendSmstooFrequently;
import cn.westv.scps.exception.UnfoundSmsTplException;
import cn.westv.scps.exception.ValiDateCodeTimeout;
import cn.westv.scps.exception.ValidateCodeErr;
import cn.westv.scps.service.bikeowner.IBikeOwnerService;
import cn.westv.scps.service.sms.masage.ISmsMessageService;
import cn.westv.scps.service.sms.template.ISmsTemplateService;
import cn.westv.scps.utils.Page;
import cn.westv.scps.utils.StringUtils;
import cn.westv.scps.web.controller.base.AbstractController;
import cn.westv.scps.web.utils.SendSmsTools;

@Controller
@RequestMapping("/sms/msg")
public class MassageController extends AbstractController<MassageController> {
	@Resource
	private ISmsMessageService sysMessageService;
	@Resource
	private ISmsTemplateService smsTemplateService;
	@Resource
	private IBikeOwnerService bikeOwnerService;

	/**
	 * 判断游客登录是否超过限制
	 * 
	 * @param mobile
	 * @return
	 */
	private boolean isAllowSend(String mobile) {
		Map<String, Integer> visitorSendSmsCountMap = SendSmsTools.visitorLoginSendSmsCountMap;
		Integer count = visitorSendSmsCountMap.get(mobile);
		if (count == null) {
			visitorSendSmsCountMap.put(mobile, 0);
			return true;
		}
		if (count < 5) {
			return true;
		}
		return false;
	}

	/**
	 * 发送短信后处理反馈给前端的信息
	 * 
	 * @param mobile
	 * @param imgCode
	 * @param tokenCode
	 * @param smsTplCode
	 * @param sst
	 * @return
	 */
	private Map<String, Object> hendleSendMassage(String mobile, String imgCode, String tokenCode, String smsTplCode,
			SendSmsTools sst) {
		Result<SmsSingleSend> result;
		try {
			result = sst.sendSmsMassage(mobile, imgCode, tokenCode, 86400000L, smsTplCode);// 短信验证如果没用过，一天后自动清除
			logger.debug(new Date() + " 发送短信情况：  " + result);
		} catch (SendSmstooFrequently e) {
			return ajaxReturnMap(OP_STATUS_FAILD, returnMsg(ConfigCodeConstant.SEND_SMSTOO_FREQUENTLY), null);
		} catch (ValidateCodeErr e2) {
			return ajaxReturnMap(OP_STATUS_FAILD, returnMsg(ConfigCodeConstant.VALIDATE_CODE_ERR), null);
		} catch (ValiDateCodeTimeout e3) {
			return ajaxReturnMap(OP_STATUS_FAILD, returnMsg(ConfigCodeConstant.VALIDATE_CODE_TIMEOUT), null);
		} catch (UnfoundSmsTplException e4) {
			return ajaxReturnMap(OP_STATUS_FAILD, e4.getMessage(), null);
		} catch (SendSmsOutOfRangeException e) {
			return ajaxReturnMap(OP_STATUS_FAILD, returnMsg(ConfigCodeConstant.SEND_SMS_OUT_OF_RANGE), null);
		}
		Integer code = result.getCode();
		if (code == 0) {// 发送短信成功
			// 记录发送短信次数
			// 游客登录次数增加--------------  已经在 sst.sendSmsMassage() 方法内进行处理了，所有此处不再处理
//			Map<String, Integer> visitorLoginSendSmsCountMap = SendSmsTools.visitorLoginSendSmsCountMap;
//			Integer count = visitorLoginSendSmsCountMap.get(mobile);
//			if (count == null) {
//				count = 0;
//			}
//			count++;
//			SendSmsTools.visitorLoginSendSmsCountMap.put(mobile, ++count);
			// 游客登录次数增加--------------
			return ajaxReturnMap(OP_STATUS_SUCCESS, "短信已经发送！", null);
		}else {
			return ajaxReturnMap(OP_STATUS_FAILD, "短信发送失败！", result);
		}
		
	}

	/**
	 * 短信群发页面
	 * 
	 * @return
	 */
	@RequestMapping(value = "/batchsend.cgi")
	public String batchSendSmsMsg_cig() {
		return "/WEB-INF/page/sms/send/batchsendMsg.jsp";
	}

	/**
	 * 分页页面
	 * 
	 * @return
	 */
	@RequestMapping(value = "/pageList.cgi")
	public String pageList_cgi() {
		return "/WEB-INF/page/sms/msg/smMsg_index.jsp";
	}

	/**
	 * 批量发送自定义短信
	 * 
	 * @param mobiles
	 * @param text
	 * @return
	 */
	@RequestMapping(value = "/batchsend") // , method = RequestMethod.POST
	@ResponseBody
	public Map<String, Object> batchSendSmsMsg(String mobiles, String text, String serialNumber) {
		if (StringUtils.isEmpty(text) || StringUtils.isEmpty(mobiles)) {
			return ajaxReturnMap(OP_STATUS_FAILD, returnMsg(ConfigCodeConstant.REQUIRED_PARAMETERS_IS_NULL), null);
		}
		try {
			String mobileExp = "1(3|4|5|7|8)\\d{9}";
			String regExp = mobileExp + "([,]{0,}" + mobileExp + "){0,}[,]{0,}";
			if (!mobiles.matches(regExp)) {
				return ajaxReturnMap(OP_STATUS_FAILD, "手机号码格式不对！", null);
			}
			String[] mobileArr = mobiles.split(",");
			SendSmsTools sst = new SendSmsTools();
			Map<String, Object> map = sst.sendBatchMessage(mobileArr, text);
			if (map != null && map.size() > 0) {
				// Result<SmsBatchSend> result = (Result<SmsBatchSend>)
				// map.get("result");
				// String serialNumber = (String) map.get("serialNumber");
				// List<SmsMessageRecordEntity> list =
				// (List<SmsMessageRecordEntity>) map.get("list");
				// System.out.println(result);
				if (StringUtils.isNotBlank(serialNumber)) {// 如果流水号不为空，则属于短信失败处理的业务逻辑
					String hql = "from SmsMessageRecordEntity where mobile in (";
					for (String mobile : mobileArr) {
						hql += " ? ,";
					}
					hql = hql.substring(0, hql.length() - 1);
					hql += ") and serialNumber = ?";
					String[] params = Arrays.copyOf(mobileArr, mobileArr.length + 1);
					params[params.length - 1] = serialNumber;
					List<SmsMessageRecordEntity> list = sysMessageService.find(hql, SmsMessageRecordEntity.class,
							params);
					for (SmsMessageRecordEntity entity : list) {
						entity.setHandleState(DBconstant.ALREADY_HANDLE_ERR);
					}
					sysMessageService.saveOrUpdateAll(list);
				}
				return ajaxReturnMap(OP_STATUS_SUCCESS, "短信已经推送!", map);
			} else {
				return ajaxReturnMap(OP_STATUS_FAILD, returnMsg("发送失败,短信提交失败！"), null);
			}
		} catch (Exception e) {
			logErr(e);
			return ajaxReturnMap(OP_STATUS_FAILD, returnMsg(ConfigCodeConstant.UNKNOWN_ERR), null);
		}
	}

	/**
	 * 发送手机验证码至指定手机号
	 * 
	 * @param mobile
	 *            手机号
	 * @param imgCode
	 *            图片验证码
	 * @param tokenCode
	 *            对应图片验证码的身份编码
	 * @param smsTplCode
	 *            短信模板编码
	 * @return
	 */
	@RequestMapping("/send/validatecode")
	@ResponseBody
	public Map<String, Object> sendMobileValidateCode(String mobile, String imgCode, String tokenCode,
			String smsTplCode) {
		if (StringUtils.isEmpty(mobile) || StringUtils.isEmpty(imgCode) || StringUtils.isEmpty(tokenCode)
				|| StringUtils.isEmpty(smsTplCode)) {
			return ajaxReturnMap(OP_STATUS_FAILD, returnMsg(ConfigCodeConstant.REQUIRED_PARAMETERS_IS_NULL), null);
		}
		try {
			SendSmsTools sst = new SendSmsTools();
			if (SmsTplCodeConstant.OWNER_REGISTER.equals(smsTplCode) ) {// 如果用户需要发送注册验证码或者修改（新手机）号码，查看数据库中是否已经存在该用户
				BikeOwnerEntity owner = bikeOwnerService.findByMobile(mobile);
				if (owner != null && owner.getAreaSever() != null) {// 如果该用户已经注册，则不给予发送注册短信或者发送修改（新手机）号码的短信
					return ajaxReturnMap(OP_STATUS_FAILD, returnMsg(ConfigCodeConstant.EXISTED_MOBILE), null);
				}
			}else if (SmsTplCodeConstant.OWNER_CHANGE_MOBILE_GPS.equals(smsTplCode)){
				BikeOwnerEntity owner = bikeOwnerService.findByMobile(mobile);
				if (owner != null) {// 如果该用户已经注册，则不给予发送注册短信或者发送修改（新手机）号码的短信
					return ajaxReturnMap(OP_STATUS_FAILD, returnMsg(ConfigCodeConstant.EXISTED_MOBILE), null);
				}
			}
			return hendleSendMassage(mobile, imgCode, tokenCode, smsTplCode, sst);
		} catch (Exception e) {
			logErr(e);
			return ajaxReturnMap(OP_STATUS_FAILD, returnMsg(ConfigCodeConstant.UNKNOWN_ERR), null);
		}
	}

	/**
	 * 获取图片验证码的图片
	 * 
	 * @param width
	 *            图宽
	 * @param height
	 *            高
	 * @param fontSize
	 *            字体大小
	 * 
	 * @return
	 * @throws IOException 
	 */
	@RequestMapping("/img/validate/code")
	@ResponseBody
	public Map<String, Object> getImgValidateCode(Integer width, Integer height, Integer fontSize) throws IOException {
		if (width == null) {
			width = 0;
		}
		if (height == null) {
			height = 0;
		}
		if (fontSize == null) {
			fontSize = 0;
		}
		try {
			String tokenCode = UUID.randomUUID().toString().replace("-", "");// 生成一个唯一的字符串为键，存入图片验证码的键值对集合中
			SendSmsTools sst = new SendSmsTools();
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			sst.createImgCode(tokenCode, out, width, height, fontSize, 50);// 创建验证码以及图片
			Map<String, Object> map = new HashMap<>();
			map.put("tokenCode", tokenCode);
			String encodeBase64String = Base64.encodeBase64String(out.toByteArray());
			map.put("img", encodeBase64String);
			out.close();
			// System.out.println(map);
			return ajaxReturnMap(OP_STATUS_SUCCESS, "", map);
		} catch (Exception e) {
			logErr(e);
			return ajaxReturnMap(OP_STATUS_FAILD, returnMsg(ConfigCodeConstant.UNKNOWN_ERR), null);
		}
	}

	/**
	 * 根据时间查询短信数量
	 * 
	 * @param beginTime
	 * @param endTime
	 * @return
	 */
	@RequestMapping("/count")
	@ResponseBody
	public Map<String, Object> getCount(Date beginTime, Date endTime) {
		try {
			String hql = "select count(*) from SmsMessageRecordEntity where returnCode = ? ";
			List<Object> params = new ArrayList<>();
			params.add(0);
			if (beginTime != null) {
				hql += " and sendTime > ? ";
				params.add(beginTime);
			}
			if (endTime != null) {
				hql += " and sendTime < ? ";
				params.add(endTime);
			}
			Long count = sysMessageService.queryHQL(hql, params.toArray(), Long.class);
			return ajaxReturnMap(OP_STATUS_SUCCESS, "", count);
		} catch (Exception e) {
			logErr(e);
			return ajaxReturnMap(OP_STATUS_FAILD, returnMsg(ConfigCodeConstant.UNKNOWN_ERR), null);
		}
	}

	/**
	 * 分页查询短信记录
	 * 
	 * @param beginTime
	 * @param endTime
	 * @param smsMessage
	 * @param page
	 * @return
	 */
	@RequestMapping("/pagelist")
	@ResponseBody
	public Map<String, Object> pageList(Date beginTime, Date endTime, SmsMessageRecordEntity smsMessage,
			Page<SmsMessageRecordEntity> page) {
		try {
			String hql = "from SmsMessageRecordEntity where 1 = 1 ";
			List<Object> params = new ArrayList<>();
			if (beginTime != null) {
				hql += " and sendTime > ? ";
				params.add(beginTime);
			}
			if (endTime != null) {
				hql += " and sendTime < ? ";
				params.add(endTime);
			}
			if (smsMessage != null) {
				String content = smsMessage.getContent();
				if (StringUtils.isNotBlank(content)) {
					hql += " and content like ? ";
					params.add("%" + content + "%");
				}
				String mobile = smsMessage.getMobile();
				if (StringUtils.isNotBlank(mobile)) {
					hql += " and mobile like ? ";
					params.add("%" + mobile + "%");
				}
				String serialNumber = smsMessage.getSerialNumber();
				if (StringUtils.isNotBlank(serialNumber)) {
					hql += " and serialNumber like ? ";
					params.add("%" + serialNumber + "%");
				}
				String handleState = smsMessage.getHandleState();
				if (StringUtils.isNotBlank(handleState)) {
					hql += " and handleState = ? ";
					params.add(handleState);
				}
			}
			Page<SmsMessageRecordEntity> findPage = sysMessageService.findPage(hql, page, SmsMessageRecordEntity.class,
					params.toArray());
			findPage.setLinks("/pagelist");
			return ajaxReturnMap(OP_STATUS_SUCCESS, "", findPage);
		} catch (Exception e) {
			logErr(e);
			return ajaxReturnMap(OP_STATUS_FAILD, returnMsg(ConfigCodeConstant.UNKNOWN_ERR), null);
		}
	}

	/**
	 * 游客登录,发送短信验证（通过短信验证进入）
	 * 
	 * @param mobile
	 * @param imgCode
	 * @param tokenCode
	 * @return
	 */
	@RequestMapping("/visitor")
	@ResponseBody
	public Map<String, Object> visitorLogin(String mobile, String imgCode, String tokenCode) {
		try {
			BikeOwnerEntity owner = bikeOwnerService.findByMobile(mobile);
			if (owner != null && owner.getAreaSever() != null) {// 如果该用户已经注册，则不给予发送注册短信
				AreaSeverEntity areaSever = owner.getAreaSever();
				if (areaSever != null) {// 拥有所属服务器，不是游客
					return ajaxReturnMap(OP_STATUS_FAILD, returnMsg(ConfigCodeConstant.CANNT_VISITOR), null);
				}
			} else {
				// 游客身份，不将数据保存至数据库
//				owner = new BikeOwnerEntity();
//				owner.setAccount(mobile);
//				owner.setMobile(mobile);
//				owner.setAreaSever(null);
//				owner.setBikeOwnerId(null);
//				bikeOwnerService.saveOrUpdate(owner);
			}
			if (isAllowSend(mobile)) {
				SendSmsTools sst = new SendSmsTools();
				return hendleSendMassage(mobile, imgCode, tokenCode, SmsTplCodeConstant.VISITOR_LOGIN, sst);
			} else {
				return ajaxReturnMap(OP_STATUS_FAILD, returnMsg(ConfigCodeConstant.VISITOR_LOGIN_COUNT_OUT_OF_RANGE),
						null);
			}
		} catch (Exception e) {
			logErr(e);
			return ajaxReturnMap(OP_STATUS_FAILD, returnMsg(ConfigCodeConstant.UNKNOWN_ERR), null);
		}
	}

	/**
	 * 验证用户手机是否匹配验证码
	 * 
	 * @param mobile
	 * @param validateCode
	 * @return
	 */
	@RequestMapping("/verify")
	@ResponseBody
	public Map<String, Object> VerifyMobile(String mobile, String validateCode, String smsTplCode) {
		if (StringUtils.isEmpty(mobile) || StringUtils.isEmpty(validateCode)) {
			return ajaxReturnMap(OP_STATUS_FAILD, returnMsg(ConfigCodeConstant.REQUIRED_PARAMETERS_IS_NULL), null);
		}
		try {
			SendSmsTools sst = new SendSmsTools();
			try {
				sst.checkMobileValidateCode(mobile, validateCode, smsTplCode, 300000L);// 5分钟内验证码有效
			} catch (ValidateCodeErr e1) {// 验证码错误
				return ajaxReturnMap(OP_STATUS_FAILD, returnMsg(ConfigCodeConstant.VALIDATE_CODE_ERR), null);// 返回验证码错误提示
			} catch (ValiDateCodeTimeout e2) {// 验证码超时
				return ajaxReturnMap(OP_STATUS_FAILD, returnMsg(ConfigCodeConstant.VALIDATE_CODE_TIMEOUT), null);// 返回验证码超时提示
			} catch (NoHaveValidateCode e3) {// 没有对应的手机验证码（可能是短信发送后超过1天，也可能是没有发送过短信，也可能是之前成注册过了）
				return ajaxReturnMap(OP_STATUS_FAILD, returnMsg(ConfigCodeConstant.VALIDATE_CODE_ERR), null);// 验证码超过1天，或者没有发送过手机验证短信，返回验证码超时,或者是用户手机号码输入错误
			}
			return ajaxReturnMap(OP_STATUS_SUCCESS, "", null);
		} catch (Exception e) {
			logErr(e);
			return ajaxReturnMap(OP_STATUS_FAILD, returnMsg(ConfigCodeConstant.UNKNOWN_ERR), null);
		}
	}
}
